package mcore

import (
	"errors"
	"net"
	"strconv"
	"strings"
)

const aBegin = 167772160
const aEnd = 184549375
const bBegin = 2886729728
const bEnd = 2887778303
const cBegin = 3232235520
const cEnd = 3232301055

func IPInner(ipAddr string) bool {
	ipNum := getIpNum(ipAddr)
	isInnerIp := isInner(ipNum, aBegin, aEnd) || isInner(ipNum, bBegin, bEnd) || isInner(ipNum, cBegin, cEnd) || ipAddr == "127.0.0.1"
	return isInnerIp
}

func IPGet(xForwardedFor string, remoteAddr string) string {
	clientIp := xForwardedFor
	if clientIp == "" || clientIp == "know" {
		if remoteAddr == "::1" {
			clientIp = "127.0.0.1"
		} else {
			clientIp = remoteAddr
		}
	}
	clientIps := strings.Split(clientIp, ",")
	if len(clientIps) <= 1 {
		return strings.Trim(clientIp, " ")
	}

	return strings.Trim(clientIps[len(clientIps)-1], " ")

}

func getIpNum(ipAddr string) int {
	ips := strings.Split(ipAddr, ".")
	a, _ := strconv.Atoi(ips[0])
	b, _ := strconv.Atoi(ips[1])
	c, _ := strconv.Atoi(ips[2])
	d, _ := strconv.Atoi(ips[3])
	return a*256*256*256 + b*256*256 + c*256 + d
}
func isInner(userIp int, begin int, end int) bool {
	return (userIp >= begin) && (userIp <= end)
}

func LocalIP() (net.IP, error) {
	ifaces, err := net.Interfaces()
	if err != nil {
		return nil, err
	}
	for _, iface := range ifaces {
		if iface.Flags&net.FlagUp == 0 {
			continue // interface down
		}
		if iface.Flags&net.FlagLoopback != 0 {
			continue // loopback interface
		}
		addrs, err := iface.Addrs()
		if err != nil {
			return nil, err
		}
		for _, addr := range addrs {
			ip := getIpFromAddr(addr)
			if ip == nil {
				continue
			}
			return ip, nil
		}
	}
	return nil, errors.New("connected to the network")
}

// 获取ip
func getIpFromAddr(addr net.Addr) net.IP {
	var ip net.IP
	switch v := addr.(type) {
	case *net.IPNet:
		ip = v.IP
	case *net.IPAddr:
		ip = v.IP
	}
	if ip == nil || ip.IsLoopback() {
		return nil
	}
	ip = ip.To4()
	if ip == nil {
		return nil // not an ipv4 address
	}

	return ip
}
